import 'dart:convert';

import 'package:aichat_flutter_wallet/module/module_browser/provider/browser_proviser.dart';
import 'package:aichat_flutter_wallet/module/module_browser/viewmodel/before_browser.dart';
import 'package:aichat_flutter_wallet/module/module_browser/widget/common_widget.dart';
import 'package:aichat_flutter_wallet/module_common/network/chains_type/ethchain.dart';
import 'package:aichat_flutter_wallet/module_common/provider/nav_key.dart';
import 'package:aichat_flutter_wallet/module_common/provider/token_info_provider.dart';
import 'package:aichat_flutter_wallet/module_common/provider/token_list_provider.dart';
import 'package:aichat_flutter_wallet/module_common/provider/wallet_info_provider.dart';
import 'package:aichat_flutter_wallet/module_common/mpc_help/createWalletTool.dart';
import 'package:aichat_flutter_wallet/module_common/utils/colors.dart';
import 'package:aichat_flutter_wallet/module_common/utils/sign.dart';
import 'package:aichat_flutter_wallet/module_common/widgets/button/bottom_button.dart';
import 'package:aichat_flutter_wallet/module_common/widgets/dialog/bottom_sheet_widget.dart';
import 'package:aichat_flutter_wallet/module_common/widgets/home_bar/home_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:lib_database/lib_database.dart';
import 'package:lib_util/lib_util.dart';
import 'package:lib_util/utils/utils.dart';
import 'package:lib_web3/lib_web3_method.dart';

import '../../../kai_print.dart';
import '../viewmodel/contract_mothed.dart';
import '../viewmodel/we3_method.dart';

enum TransDialog { InVokeDialog, TransferDialog, AuthDialog }

class TokenTransferWidget extends StatefulWidget {
  final Chain chain;
  final ETHTransaction? transactionBean;
  TransDialog? dialogType;

  TokenTransferWidget(
      {super.key, this.dialogType = TransDialog.TransferDialog, required this.chain, required this.transactionBean});

  @override
  State<TokenTransferWidget> createState() => _TokenTransferWidgetState();
}

class _TokenTransferWidgetState extends State<TokenTransferWidget> {
  // 查询主币
  List<Token> list = NavKey.getContext().read<TokenListNotifier>().tokenList;
  String walletName = NavKey.getContext().read<WalletInfoNotifier>().walletName;
  late String contract = '';
  late String? transaction;
  late String from;
  late String to;
  int gas = 0;
  int gasPrice = 0;
  String type = '';
  String? nativeValue;
  String? safeTo;
  String rpc = '';
  String contractMothed = '';
  ETHTransaction? ethTransaction;
  String mainSymbol = '';
  String tokenSymbol = '';
  late Token? token;
  late Wallet? wallet;
  late WalletInfo? walletInfo;
  double mainPrice = 0;
  double tokenPrice = 0;
  TextEditingController editingController = TextEditingController();
  bool canDoConfirm = false; // 是否能点击
  bool isWarn = false;
  String tokenBalance = '';
  @override
  void initState() {
    super.initState();
    initData();
  }

  @override
  void dispose() {
    super.dispose();
    editingController.dispose();
  }

  initData() {
    walletInfo = NavKey.getContext().read<WalletInfoNotifier>().getWalletInfoByChain(widget.chain);
    token = ObjectBox().tokenModel.getMainTokenByWalletInfoId(walletInfo!.id);

    genMainBalance();
    if (widget.chain.type == ChainType.eth && null != widget.transactionBean) {
      ethTransaction = widget.transactionBean!;
      from = ethTransaction!.from!;
      transaction = ethTransaction!.data ?? '';
      mainSymbol = widget.chain.symbol;
      rpc = NavKey.getContext().read<BrowserProvider>().nodeInfoData!.url;

      // 主币转账
      if (widget.dialogType == TransDialog.TransferDialog && isMain()) {
        contract = '';
        to = ethTransaction!.to!;
        type = 'native';
        contractMothed = 'transfer';
        tokenSymbol = mainSymbol;
        // mainPrice = token!.priceusd != null && token!.priceusd!.isNotEmpty ? double.parse(token!.priceusd!) : 0;
        tokenPrice = mainPrice;
        canDoConfirm = true;
      }
      // 代币转账
      else if (widget.dialogType == TransDialog.TransferDialog && !isMain()) {
        contract = ethTransaction?.to ?? '';
        to = '0x' + transaction!.substring(34, 74);
        type = 'token20';
        contractMothed = 'transfer';
        getTokenData(contract);
      }
      // 授权
      else if (widget.dialogType == TransDialog.AuthDialog) {
        type = 'token20';
        contract = ethTransaction?.to ?? '';
        to = '0x' + transaction!.substring(34, 74);
        contractMothed = 'approve';
        getTokenData(contract);
        BigInt num1 = BigInt.parse(
            Utils.ensureRemoveHexPrefix('0x' + ethTransaction!.data!.substring(74, ethTransaction!.data!.length)),
            radix: 16);
        BigInt num2 = BigInt.parse(
            Utils.ensureRemoveHexPrefix('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
            radix: 16);
        if (num1 >= num2) {
          isWarn = true;
        }
        getTokenBalance();
      }
      // 合约
      else if (widget.dialogType == TransDialog.InVokeDialog) {
        type = 'token20';
        contract = ethTransaction!.to!;
        to = '';
        contractMothed = transaction!.substring(0, 10);
        if (contractMotheds.containsKey(contractMothed)) contractMothed = contractMotheds[contractMothed];
        canDoConfirm = true;
      }

      gas = int.parse(ethTransaction!.gas ?? "0");
      gasPrice = int.parse(ethTransaction!.gasPrice ?? "0");
      if (isMain()) {
        nativeValue = (BigInt.parse(ethTransaction!.value!) / BigInt.from(10).pow(18)).toString();
      }

      if (null == ethTransaction!.gasPrice || null == ethTransaction!.gas) {
        _requestGasPrice();
      }
    }
  }

  bool isMain() {
    return ethTransaction!.data == null || ethTransaction!.data!.isEmpty || ethTransaction!.data == '0x';
  }

  all() {
    if (tokenBalance != '')
      setState(() {
        editingController.text = tokenBalance;
      });
  }

  genMainBalance() async {
    try {
      if (token == null && walletInfo != null) {
        await createWalletTool.createMainTokenByWalletId(walletInfo!);
      }
      context.read<TokenListNotifier>().updateTokenBalance(token).then((val) {
        if (mounted)
          setState(() {
            token = val;
          });
      });
    } catch (err) {}
  }

  getTokenBalance() async {
    try {
      DappToken? token = ObjectBox().dappTokenModel.getTokenByIdContract(widget.chain.evmInfo!.chainId, contract);
      if (token == null) {
        Map<String, dynamic>? result = await FlutterWeb3.getERC20TokenInfoByRpc(rpc, contract);
        kaiPrint(ethTransaction!.data!.substring(74, ethTransaction!.data!.length));
        token = DappToken(
            chainId: result!['chainId'],
            contract: contract,
            name: result['name'],
            symbol: result['symbol'],
            decimals: result['decimals']);
        ObjectBox().dappTokenModel.addToken(token);
      }
      tokenBalance = await FlutterWeb3.getTokenBalance(rpc, contract, from, decimals: token.decimals);
      tokenBalance =
          Utils.formatStringBalance(tokenBalance, fractionDigits: Config.balanceFixedNum, trimDecimalZero: true);
    } catch (e) {
      kaiPrint(e);
    }
  }

  getTokenData(String contract) async {
    try {
      DappToken? token = ObjectBox().dappTokenModel.getTokenByIdContract(widget.chain.evmInfo!.chainId, contract);
      if (token == null) {
        Map<String, dynamic>? result = await FlutterWeb3.getERC20TokenInfoByRpc(rpc, contract);
        kaiPrint(ethTransaction!.data!.substring(74, ethTransaction!.data!.length));
        token = DappToken(
            chainId: result!['chainId'],
            contract: contract,
            name: result['name'],
            symbol: result['symbol'],
            decimals: result['decimals']);
        ObjectBox().dappTokenModel.addToken(token);
      }
      if (mounted) {
        setState(() {
          // tokenSymbol = result!['symbol'];
          tokenSymbol = token!.symbol;
          BigInt num = BigInt.parse(
              Utils.ensureRemoveHexPrefix('0x' + ethTransaction!.data!.substring(74, ethTransaction!.data!.length)),
              radix: 16);
          nativeValue = Utils.formatStringBalance((num / BigInt.from(10).pow(token.decimals)).toString(),
              fractionDigits: 18, trimDecimalZero: true);
          canDoConfirm = true;
          editingController.text = nativeValue!;
        });
        // Future.delayed(Duration(milliseconds: 3000), () {
        //   setState(() {
        //     canDoConfirm = true;
        //   });
        // });
      }
    } catch (e) {
      kaiPrint(e);
    }
  }

  _requestGasPrice() async {
    kaiPrint(ethTransaction);
    Sign.getErc20Gas(rpc, type, jsonEncode(ethTransaction),token!.symbol).then((value) {
      if (mounted)
        setState(() {
          gasPrice = value!['gasPrice'];
          gas = value['gas'];
          ethTransaction!.gas = gas.toString();
          ethTransaction!.gasPrice = gasPrice.toString();
        });
    });
  }

  String _calGasFee() {
    return Utils.formatStringBalance((BigInt.parse((gas * gasPrice).toString()) / BigInt.from(10).pow(18)).toString(),
        fractionDigits: 18, trimDecimalZero: true);
  }

  _signTransaction() async {
    bool iscorrect = await Web3MethodCall.checkPassword();
    if (iscorrect) {
      try {
        if (editingController.text == '' && widget.dialogType == TransDialog.AuthDialog) return;
        if (nativeValue != editingController.text && widget.dialogType == TransDialog.AuthDialog) {
          DappToken? token = ObjectBox().dappTokenModel.getTokenByIdContract(widget.chain.evmInfo!.chainId, contract);
          if (token == null) {
            Map<String, dynamic>? result = await FlutterWeb3.getERC20TokenInfoByRpc(rpc, contract);
            kaiPrint(ethTransaction!.data!.substring(74, ethTransaction!.data!.length));
            token = DappToken(
                chainId: result!['chainId'],
                contract: contract,
                name: result['name'],
                symbol: result['symbol'],
                decimals: result['decimals']);
            ObjectBox().dappTokenModel.addToken(token);
          }
          BigInt num1 = BigInt.parse((editingController.text)) * BigInt.from(10).pow(token.decimals);
          String hexString = num1.toRadixString(16).padLeft(64, '0');
          ethTransaction!.data = ethTransaction!.data!.substring(0, 74) + hexString;
        }
        Navigator.of(context).pop({
          'ethTransaction': ethTransaction,
          'callback': (val) {
            Token? token = ObjectBox().tokenModel.getMainTokenByWalletInfoId(walletInfo!.id);
            if (widget.dialogType == TransDialog.TransferDialog && token != null) {
              try {
                BuildContext context = NavKey.getContext();
                context.read<TokenInfoNotifier>().insertTransaction(
                      val,
                      token,
                      to,
                      nativeValue!,
                    );
              } catch (e) {
                kaiPrint(e);
              }
            }
          }
        });
      } catch (e) {
        kaiPrint(e);
      }
    }
  }

  Widget typeWidget() {
    if (widget.dialogType == TransDialog.InVokeDialog) {
      return Container(
        padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 12.w),
        decoration: BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(10.w)),
            border: Border.all(width: 1.w, color: AppColors.c_F6F6F6)),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            CommonWidgetUtil.textWidget('data', color: AppColors.c_333333, fontsize: 12.sp),
            Text(
              transaction!,
              style: TextStyle(color: AppColors.c_333333, fontSize: 12.sp),
              // maxLines: 2,
              // overflow: TextOverflow.ellipsis,
            )
          ],
        ),
      );
    }
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          'Authorization Amount',
          style: TextStyle(color: AppColors.c_333333, fontSize: 14.sp, fontWeight: FontWeight.w600),
        ),
        SizedBox(
          height: 10.w,
        ),
        CommonWidgetUtil.tokenInputWidget(
          canInput: widget.dialogType == TransDialog.AuthDialog ? true : false,
          coinName: tokenSymbol,
          price: tokenPrice,
          value: nativeValue ?? '',
          onChange: (value) {
            kaiPrint('value===${value}');
          },
          all: () {
            all();
          },
          editingController: editingController,
        ),
        SizedBox(
          height: 10.w,
        ),
        if (widget.dialogType == TransDialog.AuthDialog && isWarn) CommonWidgetUtil.warnTipWidget(),
      ],
    );
  }

  String getTitle() {
    if (widget.dialogType == TransDialog.AuthDialog) {
      return 'Transfer Authorization';
    } else if (widget.dialogType == TransDialog.TransferDialog) {
      return 'Tonken Transfer';
    } else {
      return 'Invoke Contract';
    }
  }

  @override
  Widget build(BuildContext context) {
    WebSiteInfoItem? webSiteInfoItem = NavKey.getContext().read<BrowserProvider>().webSiteInfoItem;

    return BottomSheetWidget(
      expand: false,
      title: getTitle(),
      child: Column(
        children: [
          ConstrainedBox(
            constraints: BoxConstraints(
                maxHeight: widget.dialogType == TransDialog.AuthDialog
                    ? (550.w - MediaQuery.of(context).viewInsets.bottom)
                    : (550.w)),
            child: SingleChildScrollView(
              child: Padding(
                padding: EdgeInsets.only(left: 20.w, right: 20.w, bottom: 20.w),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    CommonWidgetUtil.websizeWidget(
                        image: webSiteInfoItem == null ? '' : webSiteInfoItem.websiteImg,
                        title: webSiteInfoItem == null ? "" : webSiteInfoItem.websiteName,
                        subTitle: webSiteInfoItem == null ? "" : webSiteInfoItem.websiteUrl),
                    SizedBox(
                      height: 10.w,
                    ),
                    if (widget.dialogType == TransDialog.AuthDialog)
                      Text(
                        'Number of Transfer Authorization Requests',
                        style: TextStyle(color: AppColors.c_333333, fontSize: 14.sp, fontWeight: FontWeight.w600),
                      ),
                    SizedBox(
                      height: 10.w,
                    ),
                    Container(
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.all(Radius.circular(10.w)),
                          border: Border.all(width: 1, color: AppColors.c_F6F6F6)),
                      padding: EdgeInsets.symmetric(horizontal: 15.w, vertical: 10.w),
                      child: CommonWidgetUtil.walletCoinInfoWidget(
                        image: widget.chain.logo,
                        coinName: mainSymbol,
                        walletName: walletName,
                        token: token,
                        chainName: widget.chain.name,
                      ),
                    ),
                    SizedBox(
                      height: 10.w,
                    ),
                    CommonWidgetUtil.textWidget(
                        'Attention! Granting this permission will give the contract access to transfer your %${tokenSymbol}% If this contract is malicious, there is a risk of theft. Please ensure that the current connection is trustworthy!',
                        color: AppColors.c_868391,
                        fontsize: 12.sp),
                    SizedBox(
                      height: 10.w,
                    ),
                    CommonWidgetUtil.contentItemWidget('From', Text(Utils.formatAddress(from))),
                    Visibility(
                      visible: to.isNotEmpty,
                      child: SizedBox(
                        height: 10.w,
                      ),
                    ),
                    Visibility(
                        visible: to.isNotEmpty,
                        child: CommonWidgetUtil.contentItemWidget('to', Text(Utils.formatAddress(to)))),
                    Visibility(
                      visible: contract.isNotEmpty,
                      child: SizedBox(
                        height: 10.w,
                      ),
                    ),
                    Visibility(
                        visible: contract.isNotEmpty,
                        child: CommonWidgetUtil.contentItemWidget(
                            'Contract Address', Text(Utils.formatAddress(contract)))),
                    SizedBox(
                      height: 10.w,
                    ),
                    CommonWidgetUtil.contentItemWidget(
                        'Gas Fee',
                        // (\$${Utils.formatStringBalance((double.parse(_calGasFee()) * mainPrice).toString(), fractionDigits: 2, trimDecimalZero: true)})
                        Text("${_calGasFee()}${mainSymbol}")),
                    SizedBox(
                      height: 10.w,
                    ),
                    CommonWidgetUtil.contentItemWidget('Contract Method', Text(contractMothed)),
                    SizedBox(
                      height: 20.w,
                    ),
                    typeWidget(),
                  ],
                ),
              ),
            ),
          ),
          Container(
              padding: EdgeInsets.fromLTRB(20.w, 0, 20.w, 0),
              child: widget.dialogType == TransDialog.TransferDialog
                  ? BottomBtn(
                      disable: !canDoConfirm,
                      textList: ['Confirm'],
                      onConfirm: _signTransaction,
                    )
                  : BottomBtn(
                      disable: !canDoConfirm,
                      textList: ['Cancel', 'Confirm'],
                      onConfirm: _signTransaction,
                      onCancel: () {
                        Navigator.of(context).pop();
                      },
                    )),
          HomeBar()
        ],
      ),
    );
  }
}
